package com.xb.loan.encryptor.comm;

import com.xb.loan.encryptor.comm.protocol.Protocol;
import com.xb.loan.encryptor.util.LogFormat;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;


public class BasicSocketClient extends Socket {

	protected static Log logger = LogFactory.getLog(BasicSocketClient.class);

	protected Protocol protocol;
	// 未初始化状态
	public static final int STATUS_NONE_INIT = 0;
	// 空闲状态
	public static final int STATUS_IDLE = 1;
	// 使用中状态
	public static final int STATUS_BUSY = 2;
	// 不可用状态
	public static final int STATUS_DISABLED = 3;
	// 连接状态
	protected int status = STATUS_NONE_INIT;
	
	protected long activeTime = System.currentTimeMillis();

	public BasicSocketClient(String hostip, int port) throws UnknownHostException,
			IOException {
		super(hostip, port);
	}

	public synchronized boolean updateStatus(int exceptStatus, int toStatus) {

		boolean flag = false;

		if (status == exceptStatus) {

			status = toStatus;

			flag = true;
		}

		return flag;
	}

	public synchronized void updateStatusForce(int toStatus) {

		status = toStatus;
	}
	
	public synchronized boolean isStatus(int exceptStatus){
		
		return status == exceptStatus;
	}

	/**
	 * 关闭该连接
	 */
	public void close() {

		try {
			
			super.close();
		} catch (IOException e) {

			logger.error(LogFormat.formatMsg("BasicSocketClient.close", this
					.toString(), "close occurs exception;"), e);

		} finally {

			updateStatusForce(STATUS_DISABLED);
		}
	}

	public void send(Object obj) {

		byte[] senddata = protocol.getEncoder().encode(obj);

		sendmessage(senddata);
	}

	public void sendmessage(byte[] msg) {

		try {
			OutputStream out = this.getOutputStream();
			if (out != null) {
				
				this.getOutputStream().write(msg);
				this.getOutputStream().flush();
			}
			
		} catch (IOException e) {

			logger.error(LogFormat.formatMsg("BasicSocketClient.sendmesage", this
					.toString(), "sendmesage occurs exception;"), e);
			updateStatusForce(STATUS_DISABLED);
		}
	}

	@SuppressWarnings("unchecked")
	private <T> T receive(InputStream input) throws IOException {

		return (T)protocol.getDecoder().decode(input);
	}

	@SuppressWarnings("unchecked")
	public <T> T receive() {

		T receiveMsg = null;

		try {
			receiveMsg = (T)receive(getInputStream());
		} catch (IOException e) {

			logger.error(LogFormat.formatMsg("BasicSocketClient.sendmesage", this
					.toString(), "sendmesage occurs exception;"), e);
			updateStatusForce(STATUS_DISABLED);
		}
		
		activeTime = System.currentTimeMillis();
		
		updateStatus(STATUS_BUSY, STATUS_IDLE);
		
		return receiveMsg;
	}

	public void setProtocol(Protocol protocol) {
		this.protocol = protocol;
	}

	public long getActiveTime() {
		return activeTime;
	}
	
	public long getIdleTime() {
		
		return System.currentTimeMillis() - activeTime;
	}
	
}
